package com.google.code.p.restrpc.core.async;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSONArray;
import com.google.code.p.restrpc.DefaultRpcResponse;
import com.google.code.p.restrpc.RpcFault;
import com.google.code.p.restrpc.core.RpcServiceProxy;
import com.google.code.p.restrpc.core.RpcServiceRepository;
import com.google.code.p.restrpc.core.async.impl.DefaultAsyncRpcResult;
import com.google.code.p.restrpc.event.RpcEventCenter;

/**
 * @author dz
 */
public class AsyncRpcServiceProxy implements Runnable {
    
    private static final Log logger = LogFactory.getLog(AsyncRpcServiceProxy.class);
    
    private AsynServiceRequest request;
    
    public AsyncRpcServiceProxy(AsynServiceRequest request) {
        this.request = request;
    }
    
    /*
     * (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run() {
        request.setStatus(AsyncServiceStatus.IN_PROCESS);
        String serviceName = request.getServiceName();
        String methodName = request.getMethodName();
        JSONArray jsonArray = (JSONArray) request.getParams();
        
        RpcServiceProxy rpcServiceProxy = RpcServiceRepository.getInstance()
                                                              .getServiceProxy(serviceName);
        
        DefaultAsyncRpcResult asyncRpcResult = new DefaultAsyncRpcResult();
        try {
            Object result = (jsonArray == null) ? rpcServiceProxy.invoke(methodName)
                                               : rpcServiceProxy.invoke(methodName,
                                                                        jsonArray);
            
            DefaultRpcResponse rpcResponse = new DefaultRpcResponse();
            rpcResponse.setSucceed(true);
            rpcResponse.setResult(result);
            
            asyncRpcResult.setFinished(true);
            asyncRpcResult.setId(request.getRequestId());
            asyncRpcResult.setRpcResponse(rpcResponse);
        }
        catch (Throwable e) {
            logger.error(e, e);
            
            DefaultRpcResponse rpcResponse = new DefaultRpcResponse();
            RpcFault fault = new RpcFault();
            fault.setMessage(e.getMessage());
            rpcResponse.setSucceed(false);
            rpcResponse.setFault(fault);
            
            asyncRpcResult.setFinished(true);
            asyncRpcResult.setId(request.getRequestId());
            asyncRpcResult.setRpcResponse(rpcResponse);
        }
        finally {
            // once the queued async service processed , publish an event to
            // notify the manager
            RpcEventCenter.getInstance()
                          .publishEvent(new AsyncRpcRequestProcessedEventObject(request,
                                                                                asyncRpcResult));
        }
        
    }
    
}
